package com.ricchieri.service;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;

import com.ricchieri.bean.CancelMultipleReservationBean;
import com.ricchieri.common.BusinessSettings;
import com.ricchieri.common.CustomAuthenticationToken;
import com.ricchieri.dao.interf.ICancelationMotiveDao;
import com.ricchieri.filter.BasicFilter;
import com.ricchieri.filter.EmailTemplateFilter;
import com.ricchieri.filter.ReservationFilter;
import com.ricchieri.model.CancelationMotive;
import com.ricchieri.model.EmailTemplate;
import com.ricchieri.model.EmailToSend;
import com.ricchieri.model.Operation;
import com.ricchieri.model.Reservation;
import com.ricchieri.model.Schedule;
import com.ricchieri.model.User;
import com.ricchieri.service.interf.ICancelationMotiveService;
import com.ricchieri.service.interf.ICancelationTypeService;
import com.ricchieri.service.interf.IEmailTemplateService;
import com.ricchieri.service.interf.IEmailToSendService;
import com.ricchieri.service.interf.IOperationService;
import com.ricchieri.service.interf.IReservationService;
import com.ricchieri.service.interf.IUserService;
import com.ricchieri.util.DateUtil;
import com.ricchieri.util.FacesUtil;

@Transactional(readOnly = true)
public class CancelationMotiveService implements ICancelationMotiveService, Serializable {
	private static final long serialVersionUID = 3752183330487717420L;
	
	ICancelationMotiveDao cancelationMotiveDao;
	IReservationService reservationService;
	IEmailToSendService emailToSendService;
	IEmailTemplateService emailTemplateService;
	IOperationService operationService;
	ICancelationTypeService cancelationTypeService;
	IUserService userService;
	
	@Override
	@Transactional(readOnly = true)
	public List<CancelationMotive> getAllCancelationMotive() {
		BasicFilter filter = new BasicFilter();
		return cancelationMotiveDao.getAllCancelationMotive(filter);
	}

	public ICancelationMotiveDao getCancelationMotiveDao() {
		return cancelationMotiveDao;
	}

	public void setCancelationMotiveDao(ICancelationMotiveDao cancelationMotiveDao) {
		this.cancelationMotiveDao = cancelationMotiveDao;
	}

	@Override
	@Transactional(readOnly = false)
	public void addMultipleCancelation(CancelMultipleReservationBean cancelationBean, User selectedUser) {
		ReservationFilter reservationFilter = new ReservationFilter();
		reservationFilter.setDni(selectedUser.getDni());
		reservationFilter.setDocumentType(String.valueOf(selectedUser.getDocumentType().getId()));
		reservationFilter.setReservationType(cancelationBean.getSelectedReservationType());
		reservationFilter.setFirstName(selectedUser.getFirstName());
		reservationFilter.setLastName(selectedUser.getLastName());
		reservationFilter.setFinish(cancelationBean.getFinishDate());
		reservationFilter.setStart(cancelationBean.getStartDate());
		reservationFilter.setTrip(cancelationBean.getSelectedTrip());
		reservationFilter.setTime(cancelationBean.getTime());
		reservationFilter.setCancel("false");
		
		List <Reservation> reservations = this.getReservationService().getAllReservationByFilter(reservationFilter);
		User currentUser = ((CustomAuthenticationToken)SecurityContextHolder.getContext().getAuthentication()).getUser();
		Schedule schedule;
		CancelationMotive canceltionMotive;
		String travel = "";
		
		for (Reservation reservation : reservations) {
			schedule = reservation.getScheduleCharter().getSchedule();
			
			if(cancelationBean.getSelectedDays().contains(String.valueOf(DateUtil.obtaintDayOfWeek(schedule.getDate())))) {
				canceltionMotive = new CancelationMotive();
				canceltionMotive.setOperator(currentUser);
				canceltionMotive.setCancelationDate(new Date(System.currentTimeMillis()));
				canceltionMotive.setCancelationDescription(cancelationBean.getCancelationDescription());
				
				BasicFilter cancelationTypeFilter = new BasicFilter();
				cancelationTypeFilter.setId(Integer.valueOf(cancelationBean.getSelectedCancelationType()));
				
				canceltionMotive.setCancelationType(getCancelationTypeService().getCancelationById(cancelationTypeFilter));
				this.getCancelationMotiveDao().add(canceltionMotive);
				
				reservation.setCancelationMotive(canceltionMotive);
				reservation.setCancel(Boolean.TRUE);
				this.getReservationService().updateReservation(reservation, Boolean.FALSE);
				
				if(isInPenalty(reservation)) {
					addCancelOperation(reservation);
					
					travel = travel.concat(DateUtil.formatDateTime(DateUtil.converToDate(reservation.getScheduleCharter().getSchedule().getDate(), reservation.getScheduleCharter().getSchedule().getTime())));
					travel = travel.concat(" ").concat(FacesUtil.getMessage("of")).concat(" ").concat(reservation.getScheduleCharter().getTrip().getFormatTrip()).concat("\n");
					
				}
			}
		}
		
		if(reservations != null && reservations.size() > 0) {
			createMultipleCancelationEmail(cancelationBean, selectedUser, currentUser);
		}
		
		if(cancelationBean.getBlock()) {
			selectedUser.setBlock(Boolean.TRUE);
			selectedUser.setBlockMotive(cancelationBean.getBlockMotive().concat("\n").concat(travel));
			getUserService().updateUser(selectedUser);
		}
	}

	private void addCancelOperation(Reservation reservation) {
		Operation cancelationOperation = new Operation();
		cancelationOperation.setAutomatic(Boolean.TRUE);
		cancelationOperation.setOperationDate(new Date(System.currentTimeMillis()));
		cancelationOperation.setOperationType(BusinessSettings.OPERATION_CANCELATION);
		cancelationOperation.setAmount(reservation.getCost());
		
		String description = FacesUtil.getMessage("travelDate").concat(" : ").concat(DateUtil.formatDate(reservation.getScheduleCharter().getSchedule().getDate()));
		description = description.concat("\n").concat(FacesUtil.getMessage("travelTime")).concat(" : ").concat(DateUtil.formatTime(reservation.getScheduleCharter().getSchedule().getTime()));
		description = description.concat("\n").concat(FacesUtil.getMessage("tripOrientation")).concat(" : ").concat(reservation.getScheduleCharter().getTrip().getFormatTrip());
		
		cancelationOperation.setObservation(description);
		cancelationOperation.setUser(reservation.getUser());
		getOperationService().addOperation(cancelationOperation);
	}
	
	private Boolean isInPenalty(Reservation reservation) {
		Date actualDate = new Date(System.currentTimeMillis());
		Date travel = DateUtil.converToDate(reservation.getScheduleCharter().getSchedule().getDate(), reservation.getScheduleCharter().getSchedule().getTime());
		
		long difference = travel.getTime() - actualDate.getTime();
		long penalty = reservation.getScheduleCharter().getTrip().getTime().getTime();
		
		if(difference < penalty) {
			return Boolean.TRUE;
		} else {
			return Boolean.FALSE;
		} 
		
	}
	
	@Override
	@Transactional(readOnly = false)
	public void addCancelation(CancelationMotive cancelMotive) {
		cancelationMotiveDao.add(cancelMotive);
	}

	@Override
	@Transactional(readOnly = false)
	public void addCancelation(CancelationMotive cancelMotive,
			Reservation reservation) {
		
		User currentUser = ((CustomAuthenticationToken)SecurityContextHolder.getContext().getAuthentication()).getUser();
		cancelMotive.setOperator(currentUser);
		cancelMotive.setCancelationDate(new Date(System.currentTimeMillis()));
		cancelationMotiveDao.add(cancelMotive);
		
		reservation.setCancelationMotive(cancelMotive);
		reservation.setCancel(Boolean.TRUE);
		this.getReservationService().updateReservation(reservation, Boolean.FALSE);
		this.createCancelationEmail(cancelMotive, reservation);
	}
	
	private void createCancelationEmail(CancelationMotive cancelMotive,
			Reservation reservation) {
		
		EmailTemplateFilter emailTemplateFilter = new EmailTemplateFilter();
		emailTemplateFilter.setEmailTemplateTypeDescription(BusinessSettings.EMAIL_TEMPLATE_CANCELATION);
		EmailTemplate emailTemplate = emailTemplateService.getEmailTemplateByFilter(emailTemplateFilter);
		
		if(emailTemplate != null && reservation.getUser().getDefaultEmail() != null) {
			EmailToSend emailToSend = new EmailToSend();
			
			String content = emailTemplate.getTemplate();
			String origenTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_ORIGIN);
			String destinyTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_DESTINY);
			String reservationDateTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_RESERVATION_DATE);
			String fullNameTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_FULLNAME);
			String reservationNumberTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_RESERVATION_NUMBER);
			String tripDateTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_TRAVEL_DATE);
			String operatorTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_OPERATOR);
			
			String dateTravel =  DateUtil.formatDate(reservation.getScheduleCharter().getSchedule().getDate());
			dateTravel = dateTravel.concat(" ").concat(DateUtil.formatTime(reservation.getScheduleCharter().getSchedule().getTime()));

			content = content.replace("{".concat(origenTag).concat("}"), FacesUtil.getMessage(reservation.getScheduleCharter().getTrip().getPlaceOrigin().getDescription()));
			content = content.replace("{".concat(destinyTag).concat("}"), FacesUtil.getMessage(reservation.getScheduleCharter().getTrip().getPlaceDestiny().getDescription()));
			content = content.replace("{".concat(reservationDateTag).concat("}"), DateUtil.formatDateTime(reservation.getReservationDate()));
			content = content.replace("{".concat(fullNameTag).concat("}"), reservation.getUser().getFullName());
			content = content.replace("{".concat(reservationNumberTag).concat("}"), String.valueOf(reservation.getId()));
			content = content.replace("{".concat(tripDateTag).concat("}"), dateTravel);	
			content = content.replace("{".concat(operatorTag).concat("}"), String.valueOf(reservation.getOperator().getFirstName()));

			emailToSend.setUser(reservation.getUser());
			emailToSend.setMessageContent(content);
			emailToSend.setEmailToSendType(emailTemplate.getEmailToSendType());
			emailToSend.setSubjectContent(emailTemplate.getSubject());
			
			emailToSendService.add(emailToSend);
		}
	}
	
	
	private void createMultipleCancelationEmail(CancelMultipleReservationBean cancelation, User selectedUser, User operator) {
		
		EmailTemplateFilter emailTemplateFilter = new EmailTemplateFilter();
		emailTemplateFilter.setEmailTemplateTypeDescription(BusinessSettings.EMAIL_TEMPLATE_MULTIPLE_CANCELATION);
		EmailTemplate emailTemplate = emailTemplateService.getEmailTemplateByFilter(emailTemplateFilter);
		
		if(emailTemplate != null && selectedUser.getDefaultEmail() != null) {
			EmailToSend emailToSend = new EmailToSend();
			
			String content = emailTemplate.getTemplate();
			String fullNameTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_FULLNAME);
			String operatorTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_OPERATOR);
			String startDateTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_START_DATE);
			String finishDateTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_FINISH_DATE);
			String daysWeekTag = FacesUtil.getMessage(BusinessSettings.EMAIL_TAG_DAYS_WEEK);
			
			content = content.replace("{".concat(fullNameTag).concat("}"), selectedUser.getFullName());
			content = content.replace("{".concat(operatorTag).concat("}"), String.valueOf(operator.getFirstName()));
			content = content.replace("{".concat(finishDateTag).concat("}"), DateUtil.formatDate(cancelation.getFinishDate()));
			content = content.replace("{".concat(startDateTag).concat("}"), DateUtil.formatDate(cancelation.getStartDate()));
			content = content.replace("{".concat(daysWeekTag).concat("}"), cancelation.obtainDescriptionSelectedDays());
			
			emailToSend.setUser(selectedUser);
			emailToSend.setMessageContent(content);
			emailToSend.setEmailToSendType(emailTemplate.getEmailToSendType());
			emailToSend.setSubjectContent(emailTemplate.getSubject());
			
			emailToSendService.add(emailToSend);
		}
	}
	
	public IEmailToSendService getEmailToSendService() {
		return emailToSendService;
	}

	public void setEmailToSendService(IEmailToSendService emailToSendService) {
		this.emailToSendService = emailToSendService;
	}

	public IEmailTemplateService getEmailTemplateService() {
		return emailTemplateService;
	}
	
	public void setEmailTemplateService(IEmailTemplateService emailTemplateService) {
		this.emailTemplateService = emailTemplateService;
	}

	public IReservationService getReservationService() {
		return reservationService;
	}

	public void setReservationService(IReservationService reservationService) {
		this.reservationService = reservationService;
	}

	public IOperationService getOperationService() {
		return operationService;
	}

	public void setOperationService(IOperationService operationService) {
		this.operationService = operationService;
	}

	public ICancelationTypeService getCancelationTypeService() {
		return cancelationTypeService;
	}

	public void setCancelationTypeService(ICancelationTypeService cancelationType) {
		this.cancelationTypeService = cancelationType;
	}

	public IUserService getUserService() {
		return userService;
	}

	public void setUserService(IUserService userService) {
		this.userService = userService;
	}
}
